package com.chen.utils;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

/**
 * 全局唯一id生成器，利用Redis的自增功能保证每个ID的唯一性。
 */
@Component
public class RedisWorker {

    /**
     * 系统开始时间戳，用于计算时间差
     */
    private static final long BEGIN_TIMESTAMP = 1640995200L; // 2022-01-01 00:00:00 的UTC时间戳

    /**
     * 序列号占用的位数
     */
    private static final long COUNT_BITS = 32; // 序列号占用32位

    private StringRedisTemplate stringRedisTemplate;

    /**
     * 构造函数，注入StringRedisTemplate
     * @param stringRedisTemplate 用于操作Redis的模板类
     */
    public RedisWorker(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * 生成下一个唯一ID
     * @param keyPrefix ID前缀，用于区分不同业务或类别的ID
     * @return 生成的唯一ID
     */
    public long nextId(String keyPrefix) {
        // 1. 计算当前时间戳（秒）
        long nowSecond = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
        long time = nowSecond - BEGIN_TIMESTAMP; // 时间差，用于占据高位

        // 2. 获取当天序列号，基于Redis自增实现
        // 根据日期生成Redis键，保证每天序列号从1开始递增
        String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
        Long increment = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);
        // 3. 将时间差和序列号拼接成最终的ID
        return time << COUNT_BITS | increment; // 左移位数后与序列号进行位或操作
    }
}
